"""
    ================================================================================
                            ------------utf-8--------------
    ================================================================================
@Author: 
    rfdsg
@Create Time: 
    2024/6/30 - 21:51
@Description:

@Attention:
    
"""
import ast
import importlib.util
import inspect
import os
import sys
from types import ModuleType
from typing import Type


def load_module_from_file(filepath: str) -> ModuleType:
    module_name = os.path.splitext(os.path.basename(filepath))[0]
    spec = importlib.util.spec_from_file_location(module_name, filepath)
    module = importlib.util.module_from_spec(spec)
    # 注册模块到 sys.modules BEFORE exec
    sys.modules[module_name] = module  # 这一步非常关键
    # 然后加载代码
    spec.loader.exec_module(module)
    return module


def get_class(path: str) -> dict[str, Type]:
    """
    注意，run输入的数据
    Args:
        path:

    Returns:

    """
    # 获取指定文件中的所有类名
    with open(path, 'r', encoding='utf-8') as file:
        node = ast.parse(file.read(), filename=path)
    class_names = [n.name for n in ast.walk(node) if isinstance(n, ast.ClassDef)]
    # 使用示例
    file_path = path  # 替换为你的文件路径
    module = load_module_from_file(file_path)
    # 获取类的对象
    classes_dict = {class_name: getattr(module, class_name, None) for class_name in class_names}
    return classes_dict


def get_fun(path: str) -> dict:
    with open(path, "r", encoding='utf-8') as source:
        tree = ast.parse(source.read(), path)

    function_name = [node.name for node in ast.walk(tree) if isinstance(node, ast.FunctionDef)]
    # 使用示例
    file_path = path  # 替换为你的文件路径
    module = load_module_from_file(file_path)
    # 获取函数对象
    fun_dict = {func_name: getattr(module, func_name, None) for func_name in function_name}
    return fun_dict


def get_all_attributes(obj):
    """ 获取对象的所有属性（包括普通属性和 property）及其值 """
    return {
        attr: getattr(obj, attr)
        for attr in dir(obj)
        if not callable(getattr(obj, attr)) and not attr.startswith("__")
    }

